package com.springboot.redis.demo.expire;

import com.springboot.redis.demo.RedisClient;
import redis.clients.jedis.Pipeline;

import java.io.IOException;

/**
 * 支持超时自动释放的分布式锁案例
 *
 * @author: zr
 * @date: 2021-11-17
 */
public class PipelineLockDemo extends RedisClient {

    public static String getKey() {
        return "timeout_lock";
    }

    /**
     * 加锁，并设置超时时间
     *
     * @param key
     * @param value
     * @param timeout
     * @return
     * @throws
     * @date 2021-11-17
     */
    public static boolean lock(String key, String value, int timeout) {
        Long result = jedis.setnx(key, value);
        jedis.expire(key, timeout);
        return result != null ? (result > 0) : false;
    }

    /**
     * 释放锁
     *
     * @param key
     * @return
     * @throws
     * @date 2021-11-17
     */
    public static boolean unlock(String key, String value) {
        String response = jedis.get(key);
        if (response == null || response.equals("") || response.equals("null")) {
            return false;
        }


        Pipeline pipelined = jedis.pipelined();
        try {
            pipelined.watch(key);
            // 判断是否是加锁的那个用户在释放锁
            if (response.equals(value)) {
                pipelined.multi();
                pipelined.del(key);
                pipelined.exec();
                return true;
            } else {
                // 如果释放锁的用户不是加锁的那个用户，就返回false，释放锁失败
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                // 关闭流水线
                pipelined.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    public static void main(String[] args) throws InterruptedException {
        String key = "lock";
        String userId = "1";
        lock(key, userId, 5);

        boolean lock = lock(key, userId, 5);
        System.out.println("加锁之后，立即重试加锁：" + (lock ? "加锁成功" : "加锁失败"));

        Thread.sleep(6000);

        boolean lock2 = lock(key, userId, 5);
        System.out.println("6秒过后，重试加锁：" + (lock2 ? "加锁成功" : "加锁失败"));

        String otherUserId = "2";
        boolean result = unlock(key, otherUserId);
        System.out.println((result ? "是你本人释放锁:" : "不是你本人释放锁:") + otherUserId);

        boolean result2 = unlock(key, userId);
        System.out.println((result2 ? "是你本人释放锁:" : "不是你本人释放锁:") + userId);
    }
}
